#if !defined(__API_MAP_H__)
#define __API_MAP_H__

#include "stdint.h"
#include "api_config.h"
#include "api_common.h"

typedef struct api_item
{
    const char *const name;
    api_fn_t fn;
} api_item_s, *api_item_t;

typedef struct api_auto_init
{
    const char *const name;
    void (*init)(void);
} api_auto_init_s, *api_auto_init_t;

#define USED __attribute__((used))
#define API_SECTION(number) __attribute__((used, section(".api." #number)))
#define ADD_API_BASE(NAME, FUN, LEVEL) const API_SECTION(LEVEL) api_auto_init_s __api_auto_init_##FUN = {.name = NAME, .init = FUN};
#define ADD_API(FUN) ADD_API_BASE(#FUN, FUN, 0)

#define HAVE_API_ITEM_ALIAS(NAME, FN) static const api_item_s __api_item_##FN = {.name = NAME, .fn = FN}
#define ADD_API_ITEM_ALIAS(NAME, FN)                   \
    do                                                 \
    {                                                  \
        HAVE_API_ITEM_ALIAS(NAME, FN);                 \
        api_add((const api_item_t) & __api_item_##FN); \
    } while (0);
#define HAVE_API_ITEM(FN) static const api_item_s __api_item_##FN = {.name = #FN, .fn = FN}
#define ADD_API_ITEM(FN)                               \
    do                                                 \
    {                                                  \
        HAVE_API_ITEM(FN);                             \
        api_add((const api_item_t) & __api_item_##FN); \
    } while (0);

void api_auto_init(void);
void api_add(const api_item_t item);
api_item_t api_get(char *name);
void api_remove(api_item_t api);
void api_call(char *name, http_server_t server, httpd_ws_frame_t *frame, void *data);
void api_list(void);

#endif // __API_MAP_H__
